home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 113_01 / a68asmln.c < prev    next >
Text File  |  1985-03-09  |  10KB  |  368 lines

  1. /*
  2.     HEADER:        CUG113;
  3.     TITLE:        6800 Cross-Assembler (BDS C Version);
  4.     FILENAME:    A68ASMLN.C;
  5.     VERSION:    2.6;
  6.     DATE:        07/22/1985;
  7.  
  8.     DESCRIPTION:    "This program lets you use your CP/M-80-based computer
  9.             to assemble code for the Motorola 6800, 6801, 6802,
  10.             6803, 6808, and 68701 microprocessors.  The program is
  11.             written in BDS C for the best possible performance on
  12.             8-bit machines.  All assembler features are supported
  13.             except relocation, linkage, listing control, and
  14.             macros.";
  15.  
  16.     KEYWORDS:    Software Development, Assemblers, Cross-Assemblers,
  17.             Motorola, MC6800, MC6801;
  18.  
  19.     SEE-ALSO:    CUG149, 6801 Cross-Assembler (Portable);
  20.  
  21.     SYSTEM:        CP/M-80;
  22.     COMPILERS:    BDS C;
  23.  
  24.     WARNINGS:    "This package is specifically tailored to CP/M-80
  25.             machines and the rather non-standard, but high-
  26.             performance BDS C compiler.  For other environments,
  27.             use the portable version of this package on CUG149.";
  28.  
  29.     AUTHORS:    William C. Colley III;
  30. */
  31.  
  32. /*
  33.     6800/6801 Cross-Assembler  v. 2.6
  34.  
  35.     May, 1980
  36.  
  37.     July, 1980 -- Rev. 2.2 consisting of fixing the M errors that
  38.         come from forward references in FDB and FCB pseudo-ops.
  39.  
  40.     October, 1980 -- Rev. 2.3 consisting of updating the assembly
  41.         language file and I/O routines to match and take
  42.         advantage of BDS C V1.4.
  43.  
  44.     October, 1983 -- Rev. 2.4 consisting of adding the CPU pseudo-op,
  45.         adding the 6801 CPU's extra opcodes, and speeding up the
  46.         code a bit.
  47.  
  48.     September, 1984 -- Rev. 2.5 consisting of fixing bugs with the symbol
  49.         table sort, the writing of files to specified drives, and the
  50.         handling of blank input lines.
  51.  
  52.     June, 1985 -- Rev. 2.6 consisting of fixing a bug in the IF block
  53.         nesting mechanism.
  54.  
  55.     Copyright (c) 1980,83,84,85 William C. Colley, III.
  56.  
  57. File:    a68asmln.c
  58.  
  59. Line assembly routine.
  60. */
  61.  
  62. /*  Get globals:  */
  63.  
  64. #include "a68.h"
  65.  
  66. /*
  67. This function is the workhorse of the assembler.  The routine
  68. gets any labels off the line and processes them, gets the opcode
  69. and builds the binary output as it evaluates the operand field.
  70. */
  71.  
  72. asmline()
  73. {
  74.     char c, label[2*SYMLEN], opcode, opattr;
  75.  
  76.     nbytes = 0;  address = pc;  directok = TRUE;
  77.     evalerr = FALSE;  hexflg = NOCODE;  label[0] = '\0';
  78.     binbuf[0] = binbuf[1] = binbuf[2] = 0x01;
  79.  
  80.     switch (getchr(&c,NOSKIP)) {
  81.     case ALPHA:    backchr;  getname(label);
  82.             if ((!label[1] && ((c = toupper(label[0])) == 'A' ||
  83.                 c == 'B' || c == 'X')) || chkoprat(label) !=
  84.                 NO_OPR) { markerr('L');  label[0] = '\0'; }
  85.             break;
  86.  
  87.     case END_LIN:    return;
  88.  
  89.     case BLANK:    break;
  90.  
  91.     default:    while((c = getchr(&c,NOSKIP)) != BLANK &&
  92.                 c != END_LIN);
  93.             markerr('L');  backchr;
  94.     }
  95.  
  96.     switch (getopcod(&opcode,&opattr)) {
  97.     case 0:     nbytes = 3;
  98.  
  99.     case -1:    opcode = 255;  opattr = 0x80; /* Set nil pseudo-op.    */
  100.  
  101.     case 1:     if ((opattr & (PSOP | IFGROUP)) == (PSOP | IFGROUP)) {
  102.             if (label[0] != '\0') markerr('L');
  103.             }
  104.             else {
  105.             if (ifstack[ifsp] != ON) return;
  106.             if (label[0]) {
  107.                 strcat(label,PADDING);
  108.                 if (pass == 1) {
  109.                 if (addsym(label)) {
  110.                     sympoint -> symvalu = pc;
  111.                     if ((opattr & PSOP) && opcode == 10)
  112.                     sympoint -> symname[1] |= 0x80;
  113.                 }
  114.                 }
  115.                 else {
  116.                 if (slookup(label)) {
  117.                     markerr('P');  label[0] = '\0';
  118.                 }
  119.                 else {
  120.                     if (sympoint -> symvalu != pc ||
  121.                     (sympoint -> symname[1] & 0x80))
  122.                     markerr('M');
  123.                     sympoint -> symname[0] &= 0x7f;
  124.                 }
  125.                 }
  126.             }
  127.             }
  128.             hexflg = PUTCODE;
  129.             if (opattr & PSOP) _psop(opcode,label);
  130.             else _normop(opcode,opattr);
  131.             return;
  132.     }
  133. }
  134.  
  135. /*
  136. Internal function to process pseudo opcodes.
  137. */
  138.  
  139. _psop(opcode,label)
  140. char opcode, *label;
  141. {
  142.     char *bptr, c, d;
  143.     unsigned t;
  144.     struct symbtbl *sptr;
  145.  
  146.     sptr = sympoint;  bptr = binbuf;
  147.     switch (opcode) {
  148.     case 0:     t = eval(START);                /* ORG    */
  149.             if (evalerr || !directok) { markerr('P');  return; }
  150.             address = pc = t;  hexflg = FLUSH;
  151.             if (!label[0]) goto chkargs;
  152.             backitem(t,VALUE);  backchr;
  153.  
  154.     case 1:     if (!label[0]) {                /* EQU    */
  155.             markerr('L');  return;
  156.             }
  157.             if (!(sptr -> symname[1] & 0x80) && errcode == 'M') {
  158.             errcode = ' ';  --errcount;
  159.             }
  160.             t = eval(START);
  161.             if (evalerr || !directok) { markerr('P');  return; }
  162.             address = sptr -> symvalu;
  163.             if (!directok) markerr('P');
  164.             if (address != (sptr -> symvalu = t)) markerr('M');
  165.             goto chkargs;
  166.  
  167.     case 2:                            /* FCB    */
  168.             while ((c = getitem(&t,SMALST)) != END_LIN) {
  169.             if (c == COMMA) t = 0;
  170.             else {
  171.                 backitem(t,c);
  172.                 if ((t = eval(START)) > 0xff && t < 0xff80) {
  173.                 markerr('V');  t = 0;
  174.                 }
  175.             }
  176.             *bptr++ = t;  ++nbytes;
  177.             }
  178.             return;
  179.  
  180.     case 3:                            /* FDB    */
  181.             while ((c = getitem(&t,SMALST)) != END_LIN) {
  182.             if (c == COMMA) t = 0;
  183.             else { backitem(t,c);  t = eval(START); }
  184.             *bptr++ = t >> 8;  *bptr++ = t;  nbytes += 2;
  185.             }
  186.             return;
  187.  
  188.     case 4:     while ((c = getchr(&d,SKIP)) != END_LIN) {    /* FCC    */
  189.             if (c == COMMA) continue;
  190.             if (c != QUOTE) { markerr('"');  return; }
  191.             while ((c = *linptr++) != d) {
  192.                 if (c == '\n') { markerr('"');  return; }
  193.                 *bptr++ = c;  ++nbytes;
  194.             }
  195.             }
  196.             return;
  197.  
  198.     case 5:     t = eval(START);                /* RMB    */
  199.             if (evalerr || !directok) { markerr('P');  return; }
  200.             pc += t;  hexflg = FLUSH;  goto chkargs;
  201.  
  202.     case 6:     if (pass == 1) --pass;            /* END    */
  203.             else {
  204.             ++pass;
  205.             if (ifsp) markerr('I');
  206.             }
  207.             hexflg = NOMORE;  goto chkargs;
  208.  
  209.     case 7:                            /* ELSE    */
  210.     case 8:     hexflg = NOCODE;                /* ENDI    */
  211.             if (!ifsp) { markerr('I');  return; }
  212.             if (opcode == 8) --ifsp;
  213.             else ifstack[ifsp] = -ifstack[ifsp];
  214.             goto chkargs;
  215.  
  216.     case 9:     address = eval(START);            /* IF    */
  217.             if (evalerr || !directok) {
  218.             markerr('P');  address = TRUE;
  219.             }
  220.             if (ifsp == IFDEPTH - 1) wipeout("\nIf stack overflow.\n");
  221.             if (ifstack[ifsp++] != ON) {
  222.             hexflg = NOCODE;  ifstack[ifsp] = NULL;
  223.             }
  224.             else ifstack[ifsp] = address ? ON : OFF;
  225.             goto chkargs;
  226.  
  227.     case 10:    if (!label[0]) {                /* SET    */
  228.             markerr('L');  return;
  229.             }
  230.             if ((sptr -> symname[1] & 0x80) && errcode == 'M') {
  231.             errcode = ' ';  --errcount;
  232.             }
  233.             address = eval(START);
  234.             if (evalerr) return;
  235.             sptr -> symvalu = address;
  236.             if (!directok) markerr('P');
  237.             goto chkargs;
  238.  
  239.     case 11:    hexflg = NOCODE;                /* CPU    */
  240.             t = eval(START);
  241.             if (evalerr || !directok) { markerr('P');  return; }
  242.             if (t != 6800 && t != 6801) { markerr('V');  return; }
  243.             extend = t == 6801;
  244.  
  245.     chkargs:    if (getitem(&c,SMALST) != END_LIN) markerr('T');
  246.             return;
  247.  
  248.     case 255:   if (!nbytes) hexflg = NOCODE;    /*  NO OPCODE    */
  249.             return;
  250.     }
  251. }
  252.  
  253. /*
  254. Internal function to process normal (non-pseudo) opcodes.
  255. */
  256.  
  257. _normop(opcode,attr)
  258. char opcode,attr;
  259. {
  260.     unsigned value, operand;
  261.     char numcntl, c;
  262.  
  263.     nbytes = 1;
  264.     numcntl = operand = 0;
  265.  
  266.     if (extend && opcode == 0x8d) attr |= DIROK;
  267.     if ((attr & IS6801) == IS6801) {
  268.     attr &= ~IS6801;
  269.     if (!extend) { nbytes = 3;  markerr('O');  return; }
  270.     }
  271.  
  272.     for (;;) {
  273.     switch (c = getitem(&value,SMALST)) {
  274.         case REGISTR:   switch (value) {
  275.                 case 'B':   if (opcode < 0x40) ++opcode;
  276.                         else opcode |= opcode < 0x80 ?
  277.                         0x10 : 0x40;
  278.  
  279.                 case 'A':   if (attr & REGOPT) {
  280.                         attr = 0;  numcntl = 2;
  281.                         break;
  282.                         }
  283.                         if (attr & REGREQ) {
  284.                         attr &= ~REGREQ;  break;
  285.                         }
  286.                         nbytes = 3;  markerr('R');
  287.                         return;
  288.  
  289.                 case 'X':   nbytes = 3;
  290.                         if (!(attr & INDEX)) {
  291.                         markerr('A');  return;
  292.                         }
  293.                         if (numcntl == 2 &&
  294.                         operand > 0xff) {
  295.                         markerr('V');  return;
  296.                         }
  297.                         numcntl = 1;  nbytes = 2;
  298.                         opcode = (opcode | 0x20) & 0xef;
  299.                         attr &= REGREQ;  break;
  300.                 }
  301.                 if ((c = getitem(&value,SMALST)) != COMMA)
  302.                 backitem(value,c);
  303.                 break;
  304.  
  305.         case IMMED:     nbytes = 3;
  306.